#pragma once

#include <compl.h>

#include <dbg/printf.h>

/* 自动化断言，能自动推测的自动推测，不能自动推测的生成运行时代码 */
/* 做不到，因为static_assert不能做eval */
// #define __ASSERT(exp, printfunc)	SASSERT_CHECK(exp, printfunc, "[SASSERT]:!" TO_STRING(exp) "AT " __FILE__ ": line " __LINE__ ", " __FUNC__)
// #define FASSERT(exp)			__ASSERT(exp, fatal)	   

/* 配置运行时ASSERT, 如果不配置则假设断言成立, 可以通知编译器进行优化 */
/* 调试级别 */
/* 如果外部传入了 */
#ifndef RUNTIME_DBG_LVL
#define RUNTIME_DBG_LVL			5	/* 现有调试级别 */
#endif

#define RUNTIME_NONCHK_LVL		0	/* 0 - 不启用调试 */
#define RUNTIME_SASSERT_LVL		1	/* 1 - 启用编译时能eval的ASSERT (可被优化) */
#define RUNTIME_ASSERT_LVL		2	/* 2 - 启用运行时ASSERT */
#define RUMTIME_ERRN_LVL		3	/* 3 - 启用ERRN打印, ERRN是对程序正确性可能会造成影响结果的打印 */
#define RUMTIME_WARN_LVL		4	/* 4 - 启用WARN打印, WARN是对程序运行性能可能造成影响结果的打印*/
#define RUMTIME_INFO_LVL		5	/* 5 - 启用INFO打印, INFO是提示信息的打印 */

/* 真的触发 fatal */
#define __DEBUG_ASSERT(cond)		if(!(cond)){ fatal("assert failed: "#cond "\n"); }
#define __DEBUG_ASSERT_DOSTH(cond, sth)	if(!(cond)){ sth;/*  fatal("assert failed: "#cond "\n"); */ }

#define __RELEASE_ASSERT(cond)		ASSUME(cond)

/* 运行时 */
#define __ASSERT(cond)			if(RUNTIME_DBG_LVL >= RUNTIME_ASSERT_LVL) { __DEBUG_ASSERT(cond); } else { __RELEASE_ASSERT(cond); }/*if(RUNTIME_ASSERT) { __DEBUG_ASSERT(cond); } else { __RELEASE_ASSERT(cond); } MIF_ELSE(EQ8(ENABLE_DBG, 1), __DEBUG_ASSERT(cond), __RELEASE_ASSERT(cond))*/
#define _ASSERT(cond)			\
do{\
	if (CAN_EVAL(cond)){ /* 编译器优化 */ __DEBUG_ASSERT(cond); }\
	else{ __ASSERT(cond);} \
}while(0)

#define ASSERT(cond)			MIF_ELSE(EQ8(RUNTIME_DBG_LVL, RUNTIME_NONCHK_LVL), __RELEASE_ASSERT(cond), _ASSERT(cond))

#define __PRINT_LVL(lvl, ...)		do{ if(RUNTIME_DBG_LVL >= lvl){ dbg_printf(__VA_ARGS__); }}  while(0)

#define PRIN_ESCAPE			"\033"
#define PRIN_DFT()			PRIN_ESCAPE"[0m"
#define PRIN_RED(...)			PRIN_ESCAPE"[31m"__VA_ARGS__
#define PRIN_YELLOW(...)		PRIN_ESCAPE"[43m"__VA_ARGS__
#define PRIN_CYAN(...)			PRIN_ESCAPE"[46m"__VA_ARGS__

#define PRIN_ULINE(...)			PRIN_ESCAPE"[4m"__VA_ARGS__

#define PRINC(color, string)		PRIN_##color () string PRIN_DFT()

#define ERRN(...)			__PRINT_LVL(RUMTIME_ERRN_LVL, PRIN_RED() "[ERROR]" PRIN_DFT() " at [" PRIN_ULINE()  __FILE__ ":" TO_STRING(__LINE__) PRIN_DFT() "] "   __VA_ARGS__) 
#define WARN(...)			__PRINT_LVL(RUMTIME_WARN_LVL, PRIN_YELLOW() "[WARN]" PRIN_DFT() " at [" PRIN_ULINE() __FILE__ ":" TO_STRING(__LINE__) PRIN_DFT() "] "  __VA_ARGS__) 
#define INFO(...)			__PRINT_LVL(RUMTIME_INFO_LVL, PRIN_CYAN() "[INFO]" PRIN_DFT() " at [" PRIN_ULINE() __FILE__ ":" TO_STRING(__LINE__) PRIN_DFT()"] "  __VA_ARGS__) 

#ifdef __unix__
	#undef TRAP
	#include <stdlib.h>
	#define TRAP()	abort()
#endif
/* 打印致命错误 */
SIN void __fatal(){
	PRINT_BACKTRACE();
	TRAP();
}
#define fatal(...)	do{ \
	dbg_printf(PRIN_RED() "[FATAL]" PRIN_DFT() " at [" PRIN_ULINE()  __FILE__ ":" TO_STRING(__LINE__) PRIN_DFT() "]\n" "error program, compile at [%s, %s]\n", __DATE__, __TIME__);\
	dbg_printf(__VA_ARGS__); \
	__fatal(); }while(0)

/* 语法糖 */
#define pre_cond(cond)			ASSERT(cond)
#define post_cond(cond)			ASSERT(cond)
#define invariant(cond)			ASSERT(cond)
